> the FreeBSD man page for access(2) includes a section titled "CAVEAT" > which says that "Access() is a potential security hole and should > never be used." Good for them. I don't know of any other system that's so aboveboard about it. > [...] i cant see why this is a hole. > can you enlighten me? access() itself is probably not a hole, in that it does what it's supposed to do. Now, I didn't write the remark you quote, and don't know what whoever did was thinking - but I can perhaps talk a little about why _I_ think access() is a potential security hole. First, I should note that this discussion applies to access() as used by setuid programs. (In a non-setuid program, access has some valid, reasonable, safe uses, such as to verify execute bits cheaply before going to all the expense of a fork and exec attempt. I've also used F_OK to avoid pathname collision in programs where robustness in the face of pathological cases is not an issue.) The problem is that it is essentially impossible to use access() for anything without introducing a race condition. The only real use of access() is to verify that the real user can perform a given access to a pathname obtained from an untrustworthy source. (If the source of the pathname is trustworthy, there's no need to check.) The problem is that there is no way to ensure that the interpretation of the pathname doesn't change between the access() call and the call that actually performs whatever the operation is. Thus, using access() lulls the programmer into a warm fuzzy sense of security for being such a good coder and performing proper checks before doing things, while actually just opening up a race condition. Perhaps if open(2) took a flag like O_REALUID, to perform access controls as the real user rather than the effective user, access() wouldn't have been created and this whole discussion would be moot. In the meantime, one is generally better off switching back to the real UID, performing the operation and fielding any errors that occur, and then (if desired) switching back to the setuid UID afterwards. Unfortunately a few antique systems can't switch back and forth like this, and among modern systems there is no way that works everywhere, so you have to either write off a good deal of portability or else litter your code with #ifdefs (or something equivalent) - which is perhaps why it's done as seldom as it is. der Mouse mouse@collatz.mcrcim.mcgill.edu